<template>
  <div class="department-container">
    <div class="app-container">
      <!-- 头部布局 -->
      <el-card>
        <!-- 用一个行列布局 -->
        <el-row
          type="flex"
          justify="space-between"
          align="middle"
          style="height: 40px"
        >
          <el-col :span="20">
            <span>江苏传智播客教育科技股份有限公司</span>
          </el-col>
          <el-col :span="4">
            <el-row type="flex" justify="end">
              <!-- 两个内容 -->
              <el-col>负责人</el-col>
              <el-col>操作</el-col>
            </el-row>
          </el-col>
        </el-row>
        <!-- 树形组件 -->
        <!--
        1. 传递一个名称为data的属性 放置组件要的数据
        2. 数据的格式有要求,不能是一个平铺的数组而应该是一个树形的数组
        3. 树形组件在渲染数据的时候默认识别的字段为标题-label 子数组必须-children
           （后端它不一定叫这个名字）
       -->
        <el-tree :data="list" :props="defaultProps" :default-expand-all="true">
          <!--
          1. 作用域插槽最新语法 抛出的数据各自是什么
          2. 如何调试它抛出的数据 先尝试用插值 改为点击事件参数打印出来
          可能的疑惑点：
             1. #default  默认插槽的简写语法
             2. 之所以可以通过解构赋值 {data} 是因为组件内部传出来的数据是一个对象 对象中有一个
                固定的属性名就叫data 所以才可以进行解构赋值

          组件: 子传父
            1. 父组件传给子组件一个自定义事件
            2. 子组件内部通过this.$emit('事件','数据')

          <e-input @change="changeHandler"/>

          @change事件从哪里来的？
          组件内部通过this.$emit('change','输入框中的数据') 这个代码组件内部已经写好了
          所以作为使用者 才能够 给组件绑定一个名称为change的事件 @change

          总结：有一半看不见组件已经做好了,我们作为开发者使用者按照文档去写另一半

          插槽：组件内部遍历生成每个树形节点的时候,把你传入的数组中的每一项经过包装处理
          然后抛出来,等待被使用，抛出来的语法结构由组件内部决定,当前抛出的结构
          {
            node:{},
            data:{}
          }
          开发者使用者：正确的按照作用域插槽接收数据的语法 解构它告诉你的属性名称即可

          任何一个组件库/插件-> 看文档！！！！
         -->
          <template #default="{data}">
            <el-row
              type="flex"
              justify="space-between"
              align="middle"
              style="height: 40px; width: 100%"
            >
              <el-col :span="20">
                <span>{{ data.name }}</span>
              </el-col>
              <el-col :span="4">
                <el-row type="flex" justify="end">
                  <!-- 两个内容 -->
                  <!-- 操作人 -->
                  <el-col>{{ data.manager }}</el-col>
                  <el-col>
                    <!-- 下拉菜单 element -->
                    <el-dropdown>
                      <span> 操作<i class="el-icon-arrow-down" /> </span>
                      <el-dropdown-menu slot="dropdown">
                        <el-dropdown-item @click.native="addDepart(data.id)">添加子部门</el-dropdown-item>
                        <el-dropdown-item @click.native="editDepart(data.id)">编辑部门</el-dropdown-item>
                        <el-dropdown-item @click.native="delDepart(data.id)">删除部门</el-dropdown-item>
                      </el-dropdown-menu>
                    </el-dropdown>
                  </el-col>
                </el-row>
              </el-col>
            </el-row>
          </template>
        </el-tree>
      </el-card>
    </div>
    <!-- 新增弹框 -->
    <el-dialog

      title="提示"
      :visible="dialogVisible"
      width="30%"
      @close="closeDialog"
      @open="openDialog"
    >
      <template #default>
        <el-form ref="addForm" :model="form" :rules="rules" label-width="120px">
          <el-form-item label="部门名称" prop="name">
            <el-input v-model="form.name" style="width:80%" placeholder="1-50个字符" />
          </el-form-item>
          <el-form-item label="部门编码" prop="code">
            <el-input v-model="form.code" style="width:80%" placeholder="1-50个字符" />
          </el-form-item>
          <el-form-item label="部门负责人" prop="manager">
            <el-select v-model="form.manager" style="width:80%" placeholder="请选择">
              <el-option
                v-for="item in managerList"
                :key="item.id"
                :label="item.username"
                :value="item.username"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="部门介绍" prop="introduce">
            <el-input v-model="form.introduce" style="width:80%" placeholder="1-300个字符" type="textarea" :rows="3" />
          </el-form-item>
        </el-form>
      </template>
      <template #footer>
        <el-button type="primary" size="small" @click="confirm">确定</el-button>
        <el-button size="small">取消</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script>
import { updateDepartments, getDepartment, delDepartments, addDepartments, getDepartDetail } from '@/api/department'
import { getEmployeeSimple } from '@/api/employee'
import transTree from '@/utils/transTree'
// import { Logger } from 'runjs/lib/common'
export default {
  name: 'Department',
  data() {
    // 对code做非重校验 不能在部门列表中出现code重复
    // 思路：
    // 1. 选择增加一个自定义校验函数
    // 2. 把所有部门的code码拿到组成一个新数组 [code1,code2.....]
    // 3. 判断一下当前输入的code码能不能在code数组中找到 如果找到代表重复 找不到不重复 校验通过

    // 编辑状态下code出现了重复
    // 原因：codeList:[1,2,3] value:2
    // 思路：codeList在编辑状态下应该去掉当前的自己
    // 解决方案：filter 判断条件 codeList中的code 是否和 this.form.code
    const validateCode = (rule, value, callback) => {
      // 把一个数组在个数不变的情况下拿到code组成一个新数组 -> map
      // this.form.code 因为双向绑定的关系一直在变
      // 单独拎出来把一开JYL单纯存一份 专门用来做判断条件的 不能随着v-model进行变化
      let codeList = []
      if (this.form.id) {
        // 编辑
        codeList = this.sourceList.map((item) => item.code)
          .filter(code => code !== this.cacheCode)
      } else {
        // 新增
        codeList = this.sourceList.map((item) => item.code)
      }
      // 在一个数组中找到某一项 -> includes
      if (codeList.includes(value)) {
        // 找到了 重复了
        return callback(new Error('当前code码出现重复'))
      } else {
        // 没找到
        callback()
      }
    }
    return {
      list: [], // 部门列表
      defaultProps: {
        label: 'name',
        children: 'children'
      },
      dialogVisible: false,
      form: {
        name: '', // 部门名称
        code: '', // 部门编码
        manager: '', // 部门管理者
        introduce: '' // 部门介绍
      },
      rules: {
        name: [
          { required: true, message: '部门名称不能为空', trigger: ['blur', 'change'] },
          { min: 1, max: 50, message: '部门名称要求1-50个字符', trigger: ['blur', 'change'] }
        ],
        code: [
          { required: true, message: '部门编码不能为空', trigger: ['blur', 'change'] },
          { min: 1, max: 50, message: '部门编码要求1-50个字符', trigger: ['blur', 'change'] },
          { validator: validateCode, message: 'code不能出现重复', trigger: ['blur', 'change'] }
        ],
        manager: [
          { required: true, message: '部门负责人不能为空', trigger: ['blur', 'change'] }
        ],
        introduce: [
          { required: true, message: '部门介绍不能为空', trigger: ['blur', 'change'] },
          { min: 1, max: 300, message: '部门介绍要求1-300个字符', trigger: ['blur', 'change'] }
        ]
      },
      managerList: [], // 部门管理者列表
      curId: '', // 当前点击项的id值
      sourceList: [],
      cacheCode: ''
    }
  },
  created() {
    this.fetchDepartmentList()
  },
  methods: {
    async fetchDepartmentList() {
      const res = await getDepartment()
      // 把一个平铺的数组先处理成组件要求的tree型结构 然后再交给响应式的数据
      this.list = transTree(res.depts)
      // 存一份原始 平铺的未经过处理的数据
      this.sourceList = res.depts
    },
    delDepart(id) {
      this.$confirm('你确认要进行删除么?', '温馨提示').then(async() => {
        await delDepartments(id)
        this.$message.success('删除成功')
        // 刷新列表
        this.fetchDepartmentList()
      })
    },
    addDepart(id) {
      // 思路：1. Dialog 2.声明一个控制显示隐藏的响应式数据 3.点击发生时修改这个数据
      this.dialogVisible = true
      this.curId = id
    },
    // 获取负责人列表
    async fetchManagerList() {
      const res = await getEmployeeSimple()
      this.managerList = res
    },
    // 关闭弹框
    closeDialog() {
      this.dialogVisible = false
    },
    // 弹框打开
    openDialog() {
      this.fetchManagerList()
    },
    confirm() {
      // 1. 兜底校验
      this.$refs.addForm.validate(async(valid) => {
        if (valid) {
          // 2. 收集表单数据接口调用
          // pid：点击时候确定的 声明一个响应式数据 每次点击时都拿到当前的id 然后放到这个响应式数据中
          if (this.form.id) {
            // 调用更新接口
            await updateDepartments(this.form)
          } else {
            await addDepartments({ ...this.form, pid: this.curId })
          }

          // 后续逻辑
          // 1. 关闭弹框
          this.dialogVisible = false
          // 2. 刷新列表
          this.fetchDepartmentList()
          // 3. 提示
          this.$message.success(`${this.form.id ? '更新成功' : '新增成功'}`)
          // 4. 清空表单
          // 5. 清除校验痕迹
          this.$refs.addForm.resetFields()
        }
      })
    },
    // 编辑
    async editDepart(id) {
      // 思路：
      // 1.打开弹框（复用新增弹框）
      this.dialogVisible = true
      // 2.调用接口数据回填
      const res = await getDepartDetail(id)
      this.form = res
      this.cacheCode = res.code
      // 3.在点击确定按钮时,区分当前是否为编辑 新增就调用新增 编辑就调用更新接口
    }
  }
}
</script>
